require 'beaker-puppet'

Beaker::DSL::Helpers::RakeHelpers.load_tasks

namespace :ci do
  namespace :test do
    desc <<-EOS
Run a limited but representative subset of acceptance tests against puppet-agent
(AIO) packages. This task is intended to reduce testing time on a per-commit
basis.

  $ SHA=<full sha> bundle exec rake ci:test:quick

SHA should be the full SHA for the puppet-agent package.
EOS
    task :quick => ['ci:check_env', 'ci:gen_hosts'] do
      ENV['TESTS'] = get_test_sample.join(",")
      Rake::Task["ci:test:aio"].invoke
    end

    desc <<-EOS
Run tests on docker quickly and easily. The docker container is set up to mount
your puppet directory in the container. This means you can edit code or test
files and rerun tests without reconfiguring your test environment.

Defaults to running all tests unless TESTS is set. TESTS is a comma seperated
list of test files to run.

  $ bundle exec rake ci:test:docker TESTS='path/to/test.rb,path/to/another/test.rb'

By default, tests are run on a centos 7 host. To change the host, set HOSTS to
a valid host string according to beaker-hostgenerator requirements.

All tests marked with a server tag will be skipped.

This task skips all cleanup. Please be sure to run `bundle exec beaker destroy`
to clean up docker containers used for testing.
EOS
    task :docker do
      begin
        ENV['HOSTS'] ||= 'centos7-64a'
        ENV['SHA'] ||= `git rev-parse HEAD`.chomp
        ENV['OPTIONS'] ||= '--preserve-hosts=always'
        ENV['OPTIONS'] += ' --test-tag-exclude=server'
        Rake::Task["ci:gen_hosts"].invoke('docker')
        hosts_file_content = YAML.load_file ENV['HOSTS']
        hosts_file_content['HOSTS'].each do |host|
          host[1]['mount_folders'] = {
            'puppet' => {
              'host_path' => "#{File.dirname(__dir__)}" ,
              'container_path' => '/build/puppet'
            }
          }
          host[1]['tag'] = 'acceptance_test_host'
        end
        File.open(ENV['HOSTS'], "w") { |f| f.write(YAML.dump(hosts_file_content)) }
        Rake::Task["ci:test:git"].invoke

      ensure
        puts <<-EOF


************************
You can modify puppet code or tests and rerun tests without modifying your test
environment.

To rerun a test or set of tests, pass a comma seperated list of tests to:

  $ bundle exec beaker exec path/to/test.rb

  or

  $ bundle exec beaker exec path/to/test.rb,path/to/another/test.rb

************************
This task skips all clean up so you can rerun tests. Don't forget to clean up
after yourself!

To clean up the docker containers used to run tests, run:

  $ bundle exec beaker destroy

************************


        EOF
      end
    end
  end

  namespace :sync do
    task :windows do
      raise 'WIN_MACHINE environment variable is required' unless ENV['WIN_MACHINE']
      win_machine = ENV['WIN_MACHINE'] + '.delivery.puppetlabs.net'
      path = ENV['LIB_DIR'] || 'type' # 'lib/puppet' prefix is implicit.
      dest_path = path.split('/')[0...-1].join
      system("scp -r #{File.dirname(__FILE__)}/../lib/puppet/#{path} Administrator@#{win_machine}:'C:/Program\\ Files/Puppet\\ Labs/Puppet/puppet/lib/ruby/vendor_ruby/puppet/#{dest_path}'")
    end
  end
end

def get_test_sample
  # This set represents a reasonable sample of puppet acceptance tests,
  # covering a wide range of features and code susceptible to regressions.
  tests = [ 'tests/direct_puppet/cached_catalog_remediate_local_drift.rb',
            'tests/resource/file/content_attribute.rb',
            'tests/face/loadable_from_modules.rb',
            'tests/language/functions_in_puppet_language.rb',
            'tests/parser_functions/calling_all_functions.rb',
            'tests/ticket_4622_filebucket_diff_test.rb',
            'tests/pluginsync/4420_pluginfacts_should_be_resolvable_on_agent.rb',
            'tests/ssl/puppet_cert_generate_and_autosign.rb',
            'tests/resource/package/yum.rb',
            'tests/resource/service/ticket_5024_systemd_enabling_masked_service.rb',
            'tests/resource/service/puppet_service_management.rb'
          ]

  # Add any tests modified within the last two weeks to the list, excluding
  # deleted ones. We can't rely on --diff-filter, because an acceptance
  # test may be modified and then deleted in the same time range.
  modified = `git log --name-only --pretty="format:" --since 2.weeks ./tests`
  tests += modified.split("\n").reject do |s|
    s.empty?
  end.collect do |s|
    s.sub('acceptance/', '')
  end.select do |s|
    s =~ /\.rb$/
  end.find_all do |s|
    File.exist?(s)
  end

  tests.uniq.sort
end
